package org.kl.bf.service.basic;

import java.lang.reflect.InvocationTargetException;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.kl.bf.entity.basic.NotifyContent;
import org.kl.bf.entity.basic.NotifyInfo;
import org.kl.bf.entity.basic.User;
import org.kl.bf.repository.basic.NotifyContentDao;
import org.kl.bf.repository.basic.NotifyInfoDao;
import org.kl.bf.repository.basic.UserDao;
import org.kl.bf.utils.BasicConstants;
import org.kl.bf.utils.CRUDUtils;
import org.kl.bf.utils.KLDynamicSpecifications;
import org.kl.bf.utils.KLSearchFilter;
import org.kl.bf.web.base.BasicController;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

/**
 * @Author hqm
 * @CreateTime 2014-3-13 下午9:11:30
 */
// Spring Bean的标识.
@Component
// 默认将类中的所有public函数纳入事务管理.
@Transactional
public class NotifyInfoService {

	private static Logger logger = LoggerFactory.getLogger(NotifyInfoService.class);
	private NotifyInfoDao notifyInfoDao;
	private NotifyContentDao notifyContentDao;
	private UserDao userDao;

	public NotifyInfo getNotifyInfo(String id) {
		return notifyInfoDao.findOne(id);
	}

	/**
	 * 保存邮件
	 * 
	 * @param notifyInfo
	 * @param receivers
	 * @param content
	 * @throws Exception
	 */
	public void saveNotifyInfo(NotifyInfo notifyInfo, String content) throws Exception {
		saveOwnNotifyInfo(notifyInfo, content, BasicConstants.ATTRIBUTE_UNREAD);
		String[] receiverArray = null;
		String[] ccsArray = null;
		String[] bccsArray = null;
		if (StringUtils.isNotBlank(notifyInfo.getReceiversName()) && notifyInfo.getReceiversName().contains(";")) {
			receiverArray = StringUtils.split(notifyInfo.getReceiversName(), ";");
		} else {
			receiverArray = StringUtils.split(notifyInfo.getReceiversName(), ",");
		}
		if (StringUtils.isNotBlank(notifyInfo.getCcsName()) && notifyInfo.getCcsName().contains(";")) {
			ccsArray = StringUtils.split(notifyInfo.getCcsName(), ";");
		} else {
			ccsArray = StringUtils.split(notifyInfo.getCcsName(), ",");
		}
		if (StringUtils.isNotBlank(notifyInfo.getBccsName()) && notifyInfo.getBccsName().contains(";")) {
			bccsArray = StringUtils.split(notifyInfo.getBccsName(), ";");
		} else {
			bccsArray = StringUtils.split(notifyInfo.getBccsName(), ",");
		}
		saveNotOwnNotifyInfo(receiverArray, notifyInfo, BasicConstants.OWNER_RECEIVER);// 保存收件人邮件
		saveNotOwnNotifyInfo(ccsArray, notifyInfo, BasicConstants.OWNER_CC);// 保存抄送人邮件
		saveNotOwnNotifyInfo(bccsArray, notifyInfo, BasicConstants.OWNER_BCC);// 保存密送人邮件
	}

	/**
	 * 工作流邮件提醒
	 * 
	 * @param to
	 * @param subject
	 * @param content
	 * @throws Exception
	 */
	public void sendNotice(String to, String subject, String content) throws Exception {
		User admin = userDao.findByTrueName(BasicConstants.Administrator_TrueName);
		if (admin == null) {
			return;
		}
		NotifyInfo entity = new NotifyInfo();
		entity.setSender(admin);
		entity.setTitle(subject);
		entity.setReceiversName(to);
		saveNotifyInfo(entity, content);
		logger.info("to:" + to + "  subject:" + subject + " content:" + content);
	}

	/**
	 * 会议邮件方法
	 * 
	 * @param send
	 * @param receivers
	 * @param subject
	 * @param content
	 * @throws Exception
	 */
	public void newNotifyInfo(String send, String receivers, String subject, String content) throws Exception {
		NotifyInfo entity = new NotifyInfo();
		User sender = userDao.findByTrueName(send);
		entity.setSender(sender);
		entity.setTitle(subject);
		entity.setReceiversName(receivers);
		saveNotifyInfo(entity, content);
	}

	/**
	 * 保存为草稿
	 * 
	 * @param entity
	 * @param receivers
	 * @param content
	 */
	public void saveDraft(NotifyInfo entity, String content) {
		saveOwnNotifyInfo(entity, content, BasicConstants.ATTRIBUTE_DRAFT);
	}

	/**
	 * 保存发件者所有的邮件
	 * 
	 * @param entity
	 * @param receivers
	 * @param content
	 * @param attribute
	 */
	public void saveOwnNotifyInfo(NotifyInfo entity, String content, int attribute) {
		entity.setStatus(BasicConstants.STATUS_UNDELETE);
		entity.setAttribute(attribute);
		entity.setSendTime(new Timestamp(new DateTime().getMillis()));
		entity.setSender(entity.getSender() == null ? new User(BasicController.getCurrentUserId()) : entity.getSender());
		entity.setOwner(BasicConstants.OWNER_SENDER);
		entity.setHasNotifyAttachment(0);// 没有附件
		entity.setReceiver(null);

		notifyInfoDao.save(entity);
		if (StringUtils.isNotBlank(content)) {
			notifyContentDao.save(new NotifyContent(entity.getId(), content));
		}

		entity.setPid(entity.getId());
		notifyInfoDao.save(entity);// 将作者所属哪条记录puuid设为其自身的uuid，因为通过puuid关联附件
	}

	/**
	 * 保存非发送人的邮件记录
	 * 
	 * @param employeeUuids
	 * @param entity
	 * @param owner
	 * @throws Exception
	 */
	private List<User> saveNotOwnNotifyInfo(String[] trueNames, NotifyInfo entity, int owner) throws Exception {
		if (trueNames != null && trueNames.length != 0) {
			for (String trueName : trueNames) {
				if (StringUtils.isBlank(trueName)) {
					continue;
				}
				NotifyInfo one = null;
				try {
					one = (NotifyInfo) BeanUtils.cloneBean(entity);
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (InstantiationException e) {
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					e.printStackTrace();
				} catch (NoSuchMethodException e) {
					e.printStackTrace();
				}
				one.setId(null);
				User e = userDao.findByTrueName(trueName);
				if (e == null) {
					continue;
				}
				one.setReceiver(e);
				one.setOwner(owner);
				notifyInfoDao.save(one);
			}
		}
		return null;
	}

	public void saveNotifyInfo(NotifyInfo entity) {
		notifyInfoDao.save(entity);
	}

	/**
	 * 回收
	 * 
	 * @param id
	 */
	public void recoverNotifyInfo(String id) {
		NotifyInfo notifyInfo = notifyInfoDao.findOne(id);
		notifyInfo.setStatus(BasicConstants.STATUS_RECOVERABLE);
		notifyInfoDao.save(notifyInfo);
	}

	/*
	 * 删除附件关联
	 */

	public void deleteJoinFileId(String joinFileId, String receiverId) {
		NotifyInfo notifyInfo = notifyInfoDao.findByJoinFileIdAndReceiverId(joinFileId, receiverId);
		notifyInfo.setJoinFileId("");
		notifyInfoDao.save(notifyInfo);
	}

	public void deleteNotifyInfo(String id) {
		notifyInfoDao.delete(id);
	}

	public List<NotifyInfo> getAllNotifyInfo() {
		return notifyInfoDao.findAll();
	}

	public Page<NotifyInfo> getUserNotifyInfo(Map<String, Object> searchParams, int pageNumber, int pageSize, String sortType,
			String orderType) {
		PageRequest pageRequest = CRUDUtils.buildPageRequest(pageNumber, pageSize, sortType, orderType);
		Specification<NotifyInfo> spec = buildSpecification(searchParams);

		return notifyInfoDao.findAll(spec, pageRequest);
	}

	/**
	 * 查询邮件所有内容，包括附件和内容
	 * 
	 * @param id
	 * @return
	 */
	public NotifyInfo getNotifyInfoAndContentAndFiles(String id) {
		NotifyInfo one = notifyInfoDao.findOne(id);
		if (one != null) {
			if (StringUtils.isNotEmpty(one.getPid())) {
				one.setNotifyContent(notifyContentDao.findByNoticeId(one.getPid()));
				one.setBasicFile(null);
				one.setCcId("");
				NotifyContent nc = one.getNotifyContent();
				if (nc != null) {
					List<NotifyInfo> receives = notifyInfoDao.findByPid(one.getPid());
					if (receives != null && receives.size() > 0) {
						nc.setAllBccName("");
						nc.setAllCcName("");
						nc.setAllReceiversName("");
						for (NotifyInfo ni : receives) {
							if (ni.getAttribute() == BasicConstants.ATTRIBUTE_UNREAD) {
								if (ni.getOwner() == BasicConstants.OWNER_RECEIVER) {
									nc.setAllReceiversName(nc.getAllReceiversName() + "<b>" + ni.getReceiver().getTrueName() + "</b>,");
								} else if (ni.getOwner() == BasicConstants.OWNER_CC) {
									nc.setAllCcName(nc.getAllCcName() + "<b>" + ni.getReceiver().getTrueName() + "</b>,");
								} else if (ni.getOwner() == BasicConstants.OWNER_BCC) {
									nc.setAllBccName(nc.getAllBccName() + "<b>" + ni.getReceiver().getTrueName() + "</b>,");
								}
							} else {
								if (ni.getOwner() == BasicConstants.OWNER_RECEIVER) {
									nc.setAllReceiversName(nc.getAllReceiversName() + ni.getReceiver().getTrueName() + ",");
								} else if (ni.getOwner() == BasicConstants.OWNER_CC) {
									nc.setAllCcName(nc.getAllCcName() + ni.getReceiver().getTrueName() + ",");
								} else if (ni.getOwner() == BasicConstants.OWNER_BCC) {
									nc.setAllBccName(nc.getAllBccName() + ni.getReceiver().getTrueName() + ",");
								}
							}
						}
						if (nc.getAllBccName().length() > 1) {
							nc.setAllBccName(nc.getAllBccName().substring(0, nc.getAllBccName().length() - 1));
						}
						if (nc.getAllCcName().length() > 1) {
							nc.setAllCcName(nc.getAllCcName().substring(0, nc.getAllCcName().length() - 1));
						}
						if (nc.getAllReceiversName().length() > 1) {
							nc.setAllReceiversName(nc.getAllReceiversName().substring(0, nc.getAllReceiversName().length() - 1));
						}
					}
				}
			}
		}
		return one;
	}

	/**
	 * 获取默认未读收件条数
	 * 
	 * @param userId
	 * @return
	 */
	public long getCountNotReadReceiver(String userId) {
		Map<String, Object> searchParams = new HashMap<String, Object>();
		searchParams.put("EQ_receiver.id", userId);
		searchParams.put("NEQ_owner", BasicConstants.OWNER_SENDER + "");// 不属于发送方，即是接收方，抄送方，密送方
		searchParams.put("EQ_status", BasicConstants.STATUS_UNDELETE + "");// 未删除
		searchParams.put("EQ_attribute", BasicConstants.ATTRIBUTE_UNREAD + "");// 小于等于未读，即未读和已读的
		return notifyInfoDao.count(buildSpecification(searchParams));
	}
	
	public List<NotifyInfo> getNotReadReceiver(Integer i, String userId){
		return notifyInfoDao.findByAttributeAndReceiverId(BasicConstants.ATTRIBUTE_UNREAD, userId);
	}
	
	/**
	 * 创建动态查询条件组合.
	 */
	private Specification<NotifyInfo> buildSpecification(Map<String, Object> searchParams) {
		Map<String, KLSearchFilter> filters = KLSearchFilter.parse(searchParams);
		Specification<NotifyInfo> spec = KLDynamicSpecifications.byKLSearchFilter(filters.values(), NotifyInfo.class);
		return spec;
	}

	@Autowired
	public void setNotifyInfoDao(NotifyInfoDao notifyInfoDao) {
		this.notifyInfoDao = notifyInfoDao;
	}

	@Autowired
	public void setNotifyContentDao(NotifyContentDao notifyContentDao) {
		this.notifyContentDao = notifyContentDao;
	}

	@Autowired
	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

}
